#pragma once

namespace TestFramework
{
    template <class T>
    class TestSharedPtr
    {
    private:
      struct Storage
      {
          Storage()
              : Value(0)
              , Counter(0)
          {
          }

          Storage(T* value)
              : Value(value)
              , Counter(1)
          {
          }

          ~Storage()
          {
              delete Value;
          }

          T* Value;
          size_t Counter;
      };

    public:
        typedef T ValueType;

        TestSharedPtr()
            : Holder(new Storage())
        {
        }

        TestSharedPtr(ValueType* value)
        {
            Holder = new Storage(value);
        }

        TestSharedPtr(const TestSharedPtr& lhs)
        {
            Holder = lhs.Holder;
            ++Holder->Counter;
        }

        ~TestSharedPtr()
        {
            --Holder->Counter;
            if (Holder->Counter == 0)
            {
                delete Holder;
            }
        }

        TestSharedPtr& operator=(TestSharedPtr& ptr)
        {
            Holder = ptr.Holder;
            ++Holder.Counter;
            return *this;
        }

        ValueType* Get() const
        {
            return Holder->Value;
        }

        ValueType* operator->()
        {
            return Holder->Value;
        }

        ValueType& operator*()
        {
            return *Holder->Value;
        }

    private:
        Storage* Holder;
    };
}
